5

This site has been very helpful for me in learning how to rewrite permalinks using add_filters to solve issues we were having when we merged two blogs into one. But, I do have one item I have been unable to find any tips for:

On the date based archives links, i.e. www.domain.com/2011/12/

I simply want to translate them to: www.domain.com/news/2011/12/

Thanks in advance for any assistance.

1
  • hate to ping an unanswered question, but client wants to go live this week and this is my last outstanding issue. Any ideas, or is this something so incredibly simple that it should have been obvious...
    – Scott C
    Commented Jan 24, 2012 at 17:28

2 Answers 2

2

The really easy way: Change your permalink structure to include a "front" part. Eg. /news/%postname%

The slightly more complicated and inflexible way: WordPress holds it's data permastruct in a property of the global WP_Rewrite object stored in $wp_rewrite. You can hook in sometime early-ish (around init) and change this.

<?php
add_action('init', 'wpse39274_change_date');
function wpse39274_change_date()
{
    global $wp_rewrite;
    $wp_rewrite->date_structure = '/news/%year%/%monthnum%/%day%';
}

Inflexible because you've hard-coded the date base (news). This works fine, and if you don't need the flexibility and want a quick fix, you should do this. Just be sure to flush your rewrite rules: visit Settings > Permalinks and hit save.

The totally awesome, but a little bit complex way: Add a field to the permalinks options page where you can specify the date base.

A class to wrap things up in.

<?php
class Custom_Date_Base
{
    const SETTING = 'custom_date_base';

    private static $ins = null;

    public static function init()
    {
        add_action('plugins_loaded', array(self::instance(), '_setup'));
    }

    public static function instance()
    {
        is_null(self::$ins) && self::$ins = new self;
        return self::$ins;
    }

    public function _setup()
    {
        // we'll hook stuff in here later
    }
}

Now we need to hook into admin_init and use the settings API to add our field to the "Optional" section. We only need to use add_settings_field because Permalink options doesn't actually use the settings API.

<?php
class Custom_Date_Base
{
    const SETTING = 'custom_date_base';

    private static $ins = null;

    public static function init()
    {
        add_action('plugins_loaded', array(self::instance(), '_setup'));
    }

    public static function instance()
    {
        is_null(self::$ins) && self::$ins = new self;
        return self::$ins;
    }

    public function _setup()
    {
        add_action('admin_init', array($this, 'settings'));
    }

    public function settings()
    {
        add_settings_field(
            'custom-date-base',
            __('Date Base', 'custom-date-base'),
            array($this, 'field_cb'),
            'permalink',
            'optional',
            array('label_for' => self::SETTING)
        );
    }

    public function field_cb()
    {
        printf(
            '<input type="text" class="regular-text" id="%1$s" name="%1$s" value="%2$s" />',
            esc_attr(self::SETTING),
            esc_attr(get_option(self::SETTING))
        );
    }
}

We also need to hook into load-options-permalink.php to save stuff (due to the lack of settings API support).

<?php
class Custom_Date_Base
{
    // snip snip

    public function _setup()
    {
        add_action('admin_init', array($this, 'settings'));
        add_action('load-options-permalink.php', array($this, 'save'));
        add_action('init', array($this, 'set_date_base'));
    }

    // snip snip

    // apparently options-permalink only halfways uses the settings api?
    public function save()
    {
        // make sure it's actually an update request.
        if('POST' != $_SERVER['REQUEST_METHOD'])
            return;

        // since this fires before the actual update stuff,
        // validate the permalink nonce.
        check_admin_referer('update-permalink');

        if(!empty($_POST[self::SETTING]))
        {
            update_option(
                self::SETTING,
                sanitize_title_with_dashes($_POST[self::SETTING])
            );
        }
        else
        {
            // remove it.
            delete_option(self::SETTING);
        }
    }
}

And finally hook into init and change the data permastruct. We can piggy-back on some build in validation that WordPress does by using WP_Rewrite::get_date_permastruct. Then it's just a matter of some regex replacement.

<?php
class Custom_Date_Base
{
    // snip snip

    public function _setup()
    {
        add_action('admin_init', array($this, 'settings'));
        add_action('load-options-permalink.php', array($this, 'save'));
        add_action('init', array($this, 'set_date_base'));
    }

    // snip snip

    public function set_date_base()
    {
        if($db = get_option(self::SETTING))
        {
            global $wp_rewrite;

            // current date permastruct
            $date_s = $wp_rewrite->get_date_permastruct();

            // get the "front" -- stuff before rewrite tags in post links
            $front = isset($wp_rewrite->front) ? $wp_rewrite->front : '/';

            // build some regex. We need to account for the global rewrite 
            // "front" as well as a possible "/date" that WP appends for
            // %post_id% permalink structure where the numbers of a Post ID
            // might conflict with with year/month/day numbers.
            $regex = '#^' . preg_quote($front, '#') . '(/date)?#ui';

            $wp_rewrite->date_structure = preg_replace($regex, "/{$db}/", $date_s);

            // apprently we need to make sure this happens?
            flush_rewrite_rules();
        }
    }
}

Here is the third option wrapped up in a plugin.

0

sounds like you need to rewrite the custom post type permalink or in this case the permastruct.

I didn't have time to test but did you try with this plugin? http://wordpress.org/extend/plugins/custom-post-permalinks/ Looks like you can edit the permalink by adding /%year%/%monthnum%/ to the post type?

Also you can take a look at the Codex here http://codex.wordpress.org/Function_Reference/register_post_type

I hope it helps.

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.