0

Is there a way to automatically set page order to the last order number upon creating new pages instead of having it set to 0?

2 Answers 2

3

You could use ajax and the admin_footer-post-new.php hook. The sql would vary depending on whether you want the highest or most recently published order number. The following returns the highest published order number + 1:

function wpse155926_set_menu_order() {
    $ret = array();

    if ( check_ajax_referer( 'wpse155926_set_menu_order_post', 'nonce', false /*die*/ ) ) {
        global $wpdb;
        //last published
        //$sql = $wpdb->prepare( 'SELECT menu_order FROM ' . $wpdb->posts . ' WHERE post_type = %s AND post_status = %s ORDER BY post_date DESC LIMIT 1', 'page', 'publish' );
        //highest published
        $sql = $wpdb->prepare( 'SELECT menu_order FROM ' . $wpdb->posts . ' WHERE post_type = %s AND post_status = %s ORDER BY menu_order DESC LIMIT 1', 'page', 'publish' );
        if ( ( $result = $wpdb->get_var( $sql ) ) !== false ) {
            $ret['menu_order'] = $result + 1;
        }
    }

    header('Content-type: application/json');
    die( json_encode( $ret ) );
}
add_action( 'wp_ajax_wpse155926_set_menu_order', 'wpse155926_set_menu_order' );

function wpse155926_admin_footer_post_new_php() {
?>
<script type="text/javascript">
jQuery(document).ready(function() {
    (function ($) {
        $.post( ajaxurl, {
                action: 'wpse155926_set_menu_order',
                nonce: <?php echo json_encode( wp_create_nonce( 'wpse155926_set_menu_order_post' ) ); ?>
            }, function(response) {
                if (response && response.menu_order) {
                    $('#pageparentdiv input[name="menu_order"]').val(response.menu_order);
                }
            }, 'json'
        );
    })(jQuery);
});
</script>
<?php
}
add_action( 'admin_footer-post-new.php', 'wpse155926_admin_footer_post_new_php' );
4
  • This works really well. One addition, though, I think the $result should be offset by one so it would be a new unique number and in the last page order. Eg. $ret['menu_order'] = ++$result;
    – Giraldi
    Commented Aug 9, 2014 at 7:02
  • Ah yes but you asked for last order number - not last + 1!
    – bonger
    Commented Aug 9, 2014 at 8:35
  • Oh, and by the way, I think you should use the commented query instead, which uses ORDER BY menu_order, since I am looking for the highest value (with the addition of the post_status, of course). That query should be the correct one.
    – Giraldi
    Commented Aug 9, 2014 at 10:15
  • Ok, updated answer per your comments.
    – bonger
    Commented Aug 9, 2014 at 10:41
2

You could hook into the publish_page transitional status action and use a simple SQL query (via $wpdb) to determine the highest current value of menu_order in the {prefix}_posts table and set the menu_order of the new page accordingly. Example code:

add_action( 'publish_page', 'wpse155926_set_to_last_page', 10, 2 );
function wpse155926_set_to_last_page( $ID, $post ) {
  if ( $post->menu_order === 0 ) {
    global $wpdb;
    $query = "SELECT MAX(menu_order) FROM $wpdb->posts WHERE post_type LIKE 'page' AND post_status LIKE 'publish';";
    $max_menu_order = $wpdb->get_var( $query );
    $post->menu_order = ++$max_menu_order;
    remove_action('publish_page', 'wpse155926_set_to_last_page');
    wp_update_post( $post );
    add_action('publish_page', 'wpse155926_set_to_last_page');
  }
}
5
  • I think menu_order is shared between the different types of posts, including nav menu items even. @bonger's query seems to be better targeted. Also, with your code, publishing the page seems to take ages and then leads to a blank page.
    – Giraldi
    Commented Aug 9, 2014 at 6:55
  • I think I found the solution to the blank page issue: infinite loop. In your case, anyway, the publish_page action should be removed and then re-added. With this fix, along with @bonger's query, the overall code is working in the right direction... Still testing, though.
    – Giraldi
    Commented Aug 9, 2014 at 7:33
  • Okay, your code with the above fixes seems to work. However, the process runs on every update of the page, thus moving any updated page to the last order. So I added a condition within the function to set the page order ONLY if it is not already set: if ( $post->menu_order === 0 ) {}
    – Giraldi
    Commented Aug 9, 2014 at 8:23
  • Mind if update your answer with the fixes?
    – Giraldi
    Commented Aug 11, 2014 at 19:36
  • Answer updated. Commented Aug 13, 2014 at 10:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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