0

I'm very excited about Camaleon cms for rails 5; however, I've noticed a significant problem with posts that have parent slugs or have post-type slugs in the url as a url format.

For background, it's very important that a post's content can only be reached via one single url. Otherwise, you have the potential for getting penalized in google for having duplicate content. For those who rely on search engine traffic (basically everyone who would ever use a CMS), this is a very serious issue.

The following is an example of the issue. All of these urls will render the same post content:

http://www.example.com/parent_slug/post_slug

http://www.example.com/post_slug

http://www.example.com/parent_slug_blah_blah/post_slug

Or

http://www.example.com/post_type/post_slug

http://www.example.com/post_slug

http://www.example.com/post_type_blah_blah/post_slug

The way Wordpress deals with this issue is to redirect to the proper url with the correct parent slug if it doesn't exist or if it is misspelled.

My question here is for those in the know, is this perhaps a priority issue in one of the upcoming releases?

S Sanford
  • 1
  • 2

1 Answers1

0

I'm not sure if this will work for everyone, but here's my solution to this issue.

Requirements: this will only work for posts that have the "post_of_posttype", "heirarchy_post" or "post_of_category_post_type" route formats.

The following code is extending the functionality of Camaleon's frontend controller method render_post by simply adding a redirect when the params don't match the @post.the_path. Seems to work for my purposes. Hopefully it will help someone else.

Create a new file in your config/initializers folder and place the following code:

# config/initializers/camaleon_custom_post.rb
CamaleonCms::FrontendController.class_eval do

# render a post
# post_or_slug_or_id: slug_post | id post | post object
# from_url: true/false => true (true, permit eval hooks "on_render_post")
def render_post(post_or_slug_or_id, from_url = false, status = nil)
    if post_or_slug_or_id.is_a?(String) # slug
        @post = current_site.the_posts.find_by_slug(post_or_slug_or_id)
    elsif post_or_slug_or_id.is_a?(Integer) # id
        @post = current_site.the_posts.where(id: post_or_slug_or_id).first
    else # model
        @post = post_or_slug_or_id
    end

    unless @post.present?
        if params[:format] == 'html' || !params[:format].present?
            page_not_found()
        else
            head 404
        end
    else
        @post = @post.decorate
        if ["post_of_posttype","hierarchy_post"].include? @post.the_post_type.contents_route_format
            if params[:parent_title].nil? && params[:post_type_title].nil?
                params_path = "/" + params[:slug]
            elsif !params[:parent_title].nil?
                params_path = "/" + params[:parent_title] + "/" + params[:slug]
            elsif !params[:post_type_title].nil?
                params_path = "/" + params[:post_type_title] + "/" + params[:slug]
            end
            unless (@post.the_path === params_path)
                redirect_to @post.the_url, status: 301 and return
            end
        elsif @post.the_post_type.contents_route_format === "post_of_category_post_type"
            if [params[:post_type_title],params[:label_cat],params[:category_id],params[:title]].all?
                params_path = [params[:post_type_title],params[:label_cat],params[:category_id] + "-" + params[:title],params[:slug]].join("/")
                params_path.prepend("/")
                unless (@post.the_path === params_path)
                    redirect_to @post.the_url, status: 301 and return
                end
            else
                redirect_to @post.the_url, status: 301 and return
            end
        end
        @object = @post
        @cama_visited_post = @post
        @post_type = @post.the_post_type
        @comments = @post.the_comments
        @categories = @post.the_categories
        @post.increment_visits!
        # todo: can_visit? if not redirect home page
        home_page = @_site_options[:home_page] rescue nil
        if lookup_context.template_exists?("page_#{@post.id}")
            r_file = "page_#{@post.id}"
        elsif @post.get_template(@post_type).present? && lookup_context.template_exists?(@post.get_template(@post_type))
            r_file = @post.get_template(@post_type)
        elsif home_page.present? && @post.id.to_s == home_page
            r_file = "index"
        elsif lookup_context.template_exists?("post_types/#{@post_type.the_slug}/single")
            r_file = "post_types/#{@post_type.the_slug}/single"
        elsif lookup_context.template_exists?("#{@post_type.slug}")
            r_file = "#{@post_type.slug}"
        else
            r_file = "single"
        end

        layout_ = nil
        meta_layout = @post.get_layout(@post_type)
        layout_ = meta_layout if meta_layout.present? && lookup_context.template_exists?("layouts/#{meta_layout}")
        r = {post: @post, post_type: @post_type, layout: layout_, render: r_file}
        hooks_run("on_render_post", r) if from_url

        if status.present?
            render r[:render], (!r[:layout].nil? ? {layout: r[:layout], status: status} : {status: status})  
        else
            render r[:render], (!r[:layout].nil? ? {layout: r[:layout]} : {})
        end
    end
  end
end

Seems kind of strange the mandatory redirect for non-accurate urls is not in the core camaleon application, but perhaps most people who use this cms are creating internally facing apps. Anyway, if that's not the case, I think this should be a priority fix.

S Sanford
  • 1
  • 2