Yes - it's a feature called Plumbing. It's not 100% working yet but the basic functions are there. Need to get it finished ASAP so I can move on and get the websites finished that I'm building all of this for :)
The features it provides are as follows:
- Specify a base URL for content. There's an option to automatically base it on the content type name, or you can specify a custom base URL.
- Create nested URLs based on connections between content.
To illustrate these features, imagine you have a content type called Category, and a content type called Product. Products are then placed in Categories via a connector content type called CategoryToProduct. That's all done with the base Mechanics feature.
Then by using the Plumbing parts, you can make it so your products will be on URLs like this: /categories/books/watership-down. So that's a base URL for Category content type, then a Category called Books, then a Product called "Watership Down".
It can get more complicated than this. You could create a multi-level categories hierarchy, using a further connector which we'll call CategoryChild. This links categories to categories with a child relationship. Here we can also use a Plumbing part to create
deeper nested URLs. Now we can have /categories/books/fiction/watership-down. There are practically infinite permutations of the ways you can build URLs with these parts, and even then I have a couple of event hooks in case you need further control.
Current issues with the system are:
- Home pages are broken. I had it working but there was a regression after the latest load of refactoring.
- Nested URLs won't all be updated to reflect a change in the slug of an item, or when an item is deleted - although on site restart, all URLs will get rebuilt.
- Changing the Part Settings will also not update URLs. This is a more complex issue. I can handle this in most cases. But if you
remove one of the parts, the URLs will carry on working until the site restart. If you
add a part, I might not be able to create URLs unless you also save the setting. I haven't yet found any event where I can handle a part getting added or removed; so I don't think there's anything I can do about this - although it seems like
a good candidate to raise a workitem, I can imagine a lot of situations where you'd want to perform work on add/remove part.
- There are some other odd bugs, untested scenarios, and missing settings. Quite frankly the code is diabolical; but I needed to just get certain things working to be able to complete a couple of websites, and I'm afraid coding standards went out the window.
I'll be refactoring to improve and optimize things later.
- There's no way right now to migrate existing titles and slugs to the new routing. This is a pain and something I want to support; but since I'm using this on brand new websites, I don't need it myself right now, and time constraints mean it'll have to
wait (but if anyone else wants to look into it, shouldn't be too hard)
There's no documentation so I'll quickly explain the relevant Parts. Again I can't write any docs until I've got these two sites live. This is an area where I'd really appreciate any help - producing detailed documentation and examples will just further
delay me finishing features and working on new stuff :)
- TitlePart. I wanted a title storage mechanism that was completely independent of routing. So this is it; it'll render a title and URL, same as RoutePart currently does, but it'll just take whatever View route is available in metadata,
whichever routing system that comes from. You can also implement ITitledAspect on your own part, and that will be used for slug generation instead.
- PipeRoutePart. This gives you the options for base URLs. It also lets you choose whether that content type will be a "RootRoute" - meaning whether it's available at the top level of the URL tree, or whether it has to be accessed as a child
URL of another content item.
- DrillRoutePart. You create
nested URLs by adding this to a Connector content type. So it has to be on a content type that also has
ConnectorPart. It can also act as a "filter" route - where the parent content item will still be the main detail display, but a particular connector type will get filtered across the route. That probably sounds very confusing because it is!
But it's something I needed and it'll make a lot more sense with demonstration.
If anyone needs any specific help using this then please contact me. PipeRoutePart as it stands is pretty straightforward; it's DrillRoutePart that I know will cause real problems :)