rainlab/sitemap-plugin

URL rendering default instead of category in path

RCheesley opened this issue · 14 comments

I'm having a problem when I try to use the blog category posts option, in that all the posts are being rendered with /default/ instead of the category.

I'm not sure if this is a bug with the sitemap plugin or something to do with the setup we have - the URL's all render fine on the front-end in the blog itself, and when I use blog category it has the correct URL as well.

Any ideas?

Zmove commented

For what I experienced, it seems that the module is not compatible with dynamic url. It can't replace url with parameters like :slug with all possible urls.

It's a shame because, except for small website of 5-6 static pages, this plugin is useless actually

Yeah, pretty frustrating hey!

@w20k any ideas if this can be fixed/addressed? It effectively means blog categories can't have their posts listed out on the sitemap because the URL structure is incorrect.

I guess a way round it might be to figure out how the front-end of the site picks the correct category and generates the correct routing, and use that in order to generate the URL? (my best guess as a non-developer who isn't overly well versed in how October works!)

Related Blog plugin issue: rainlab/blog-plugin#437

@RCheesley Instead of using the All Blog Posts type in the Sitemap, could you instead use the Blog category posts type in the Sitemap, and link it to the page with the :category slug? It would mean you would have to create a sitemap item for each individual category, but it would at least be a workaround for now.

Is there any workaround or any plans to fix this issue anytime soon?

The way to properly use the blog post page url is to NOT use a category slug but have the category saved in the session when opening a blog post from a blog category page. Here is a sample of my blog category page (blog/category.htm):

title = "Blog Category Posts"
url = "/blog/:slug?"
layout = "default"
is_hidden = 0

[blogCategories]
displayEmpty = 0
categoryPage = "blog/category"

[blogPosts]
categoryFilter = "{{ :slug }}"
noPostsMessage = "No posts found"
sortOrder = "published_at desc"
categoryPage = "blog/category"
postPage = "blog/post"
==
function onInit()
{
    Session::put('category', $this->param('slug'));
}
==

And here's the Blog Post page (blog/post.htm):

title = "Blog Post"
url = "/post/:slug/"
layout = "default"
is_hidden = 0

[blogPost]
slug = "{{ :slug }}"
categoryPage = "blog/category"
==
function onInit()
{
    $this['categorySlug'] = $category = Session::get('category');
}
==
{% set category = categorySlug ? post.categories.where('slug', categorySlug).first %}
{% set prev = blogPost.previousPost %}
{% set next = blogPost.nextPost %}
{% set banner = post.featured_images|first %}
{% set summary = html_clean(post.summary) %}
{% set content = html_clean(post.content) %}
...

With this way of saving the current category in the session, the RainLab.Sitemap can be used without problems.

Hope this helps.

Thanks @mjauvin I moved my site(s) from Joomla to OctoberCMS where category is everything and I have a lot of blog posts which i cannot move to a new URL. That is the reason for not using /blog/post/:slug instead i use /blog/:categorySlug/:slug
I realized the multiple category thing when building the site, so i choose only 1 category per post.
I am trying to find where the default applies when generating so i can try and modify.

Thanks

It's feasible, but you'd have to create a plugin to do this. I don't have time right now, but I can show you the way.

This plugin will need to create a new menu item type (call it "all-blog-posts-with-categories" maybe)...

Basically, you need to replicate what the RainLab.Blog plugin does in its Post model, look at the following in models/Post.php:

  • getMenuTypeInfo()
  • resolveMenuItem()
  • getPostPageUrl()

I suggest creating a new method getPostWithCategoryPageUrl(), something like:

protected static function getPostWithCategoryPageUrl($pageCode, $post, $theme)
{   
    $page = CmsPage::loadCached($theme, $pageCode);
    if (!$page) {
        return;
    }   
 
    $params = [ 
        'slug' => $post->slug,
        'categorySlug' => $post->categories->first()->slug,
        'year'  => $post->published_at->format('Y'),
        'month' => $post->published_at->format('m'),
        'day'   => $post->published_at->format('d')
    ];  
    $url = CmsPage::url($page->getBaseFileName(), $params);

    return $url;
}

And replace the call to getPostPageUrl() in your resolveMenuItem() to getPostPageUrl(...)

Thanks @mjauvin I will try to build this and post here if i am successful :)
Thanks a lot for the help

Thanks a lot @mjauvin it works as expected.

If you're willing to share your code here for others benefit, that would be nice!

I did a quick and dirty workaround did not extend the plugin. You already gave the code :) needed for this. All i did was copy that function in post model and change the URL under all-blog-posts item.

elseif ($item->type == 'all-blog-posts') {
$result = [
'items' => []
];

        $posts = self::isPublished()
        ->orderBy('title')
        ->get();

        foreach ($posts as $post) {
            $postItem = [
                'title' => $post->title,
                // 'url'   => self::getPostPageUrl($item->cmsPage, $post, $theme),
                'url'   => self::getPostWithCategoryPageUrl($item->cmsPage, $post, $theme),
                'mtime' => $post->updated_at
            ];

            $postItem['isActive'] = $postItem['url'] == $url;

            $result['items'][] = $postItem;
        }
    }

I will be extending the blog plugin to get this fixed for good. When I am done with that plugin, i will share it here or publish it.

Note: no need to actually extend the Blog plugin, just create a plugin that adds a new menuTypeInfo.