Hyper-dynamic Drupal sites with Panels and Views

The motivation for writing this article came from my feeble attempts at trying to discuss a module I'm actively working on (to be covered in a future article) with several very intelligent Drupal developers. Due to the inherently abstract nature of the issues, and for lack of a common language, the end result was that in every case each person just ended up scratching their heads at me without really comprehending what I was really trying to get at.

Hyper-dynamic defined
Technically speaking, Drupal offers a dynamic framework right out of the box, right, so what is meant by "hyper-dynamic"?

Hyper-dynamic, for lack of a better description, refers to sites/sections-of-a-site for which pages do not exist as individual nodes, AND which (for example) are more complex than a single static view/panel. A panel/view which takes arguments, particularly multiple arguments, is an example of hyper-dynamic content delivery.

Getting down to business...
How is this idea of hyper-dynamic content useful and/or or what are the use cases?

As a 'simple' example, let's say we have a multi-regional travel site which caters to people looking for info/deals on casinos. For each region, we'd like to have a separate homepage, AND separate landing pages for each casino within the region. Finally, let's throw in a "Deals" subpage for every region/casino.

So the site hierarchy would look like this:

Name that tune
The challenge is to figure out the fewest parts we can make this architecture, while still maintaining flexibility/maintainability/upgradability.

In this case, we can accomplish our proposed site hierarchy, for an unlimited number of regions/casinos, with as little as 3 views, 3 panels, 2 content-types, and a handful or arguments:

Views used
1. "Node listing" - provides node-listing for each region/casino determined by arguments. This view is placed in the "Landing panel" (see below).
2. "Deals listing" - provides deals node-listing for each region/casino. This view is placed within the "Deals panel" (see below).
3. "Homepage listing" - provides node-listing for homepage. This view is place within the "Homepage panel" (see below).

Panels used
1. Landing panel - Provides complete landing page for each region/casino based on arguments
2. Deals panel - Provides complete "Deals" subpage for each region/casino based on arguments
3. Homepage panel - Provides homepage. Could theoretically even get away with just using the landing panel for this, but by using a separate one for the homepage we get a little more
flexibility and sanity.

Content-types
1. "Article" - a general container that can be promoted to appear on any given region/casino landing page or the site homepage.
2. "Deal" - includes specialized fields, and which will appear on the "Deals" subpages for each region/casino and which can also be promoted to appear on any given region/casino landing page.

Other issues
While having the possibility of an infinite number of regions/casinos and a gazillion pages from just 3 views, and 3 panels is pretty awesome, there are some considerations that come along with doing this:

Urls
With all of those arguments we sure are going to have some ugly urls aren't we? Well, not if we set some path aliases.

Breadcrumbs
How are we going to get our wonderful breadcrumb trail for each of this hyper-dynamic pages? Not the normal way that's for sure. If we're using our path aliases intelligently, here's something that can work though.

A "Deals" link
We will need a "Deals" link to appear on each region/casino landing page, and on each of the individual "deal" nodes for a given region/casino, and on the "Deals" page itself within each region/casino. How in the world to get such a thing without making a custom menu for each of our regions/casinos and setting the visibility on it? This is the very issue that I'm addressing with a module I've made and am working on a UI for, atm.

I'm planning on a follow up article on this subject, so please leave productive thoughts, ideas, questions that might be worth taking into account below. :-)

13 December, 2007

Comments

I'm building a site with a similar structure, yet it's a lot more chaotic due to the client's weird ideas.

I'm interested in seeing what you come up with.

...but also a fair bit of them for custom fields (e.g., 'promote to region home page? yes/no')

http://upstater.propercc.com is the development site. This would be our third and final attempt to get this site up. It works great now. Let me know if this is what your speaking of. I might be of assistance to your project.

The method you proposing for showing content is how many sites operate. I'm glad to see you are bringing this to the Drupal community. Not having a clear way of offering breaking down what is available based on the sections has been the largest pitfall.

I'm quite surprised this issue has not come up sooner. Without this ability Drupal feels more like a CMS/Blog hybrid and not a true CMS. Thanks for sharing this. And I'd like to know if you continue to work on this area of Drupal in the future.

I haven't had any time to throw at this lately - but you may want to check out the Context UI module, which I haven't used, but which I've heard/read can handle this type of functionality.

Building a site like you describe, and it's all based on Panels + Views + Taxonomy, and Views templates. Very LITTLE of the navigation and content is native to Drupal. All page URLs go through Panels Pages, and "/node" will be blocked off entirely at the forward proxy or firewall.

Panels + Terms for navigation opens the doors to interesting design patterns... but also it locks you out of some useful Drupal modules.

Drupal Site Map expects you to use paths registered with Drupal, like /node or possibly something in Panels.. but it will NOT spider all the terms in a Vocabulary (even though all those terms point to Panels pages); so you will need to build your site map using an external web spidering tool.

Panels now supports View Contexts, so if you are building a mashup page with lots of related content, you can use a view to set Panels Page "Page Title" based on the view. With terms as navigation, the ususal Node context (which works) will not suit the task. UN-fortunately, the new Views Context support in Panels is limited (it WILL query a View and get your fields back.. but it will NOT send argument contexts to the View... so if you are looking to get Page Title based on a Term or Content Taxonomy attached to that content... forget it, for now anyways [it is a Panels TODO to finish this]). Ultimately the solution to the title issue will occur when exporting Panels and Views, and a little code in the exported PHP will set page title appropriately.

This is not a complaint, but a warning to all who go down this path and have never done it before.

Drupal 7 will require FAR less hacks for this type of site design, by the way. For example, we found we had to create dummy content types (who contain the matching Taxonomy Term), and the reason was because Terms in D6 do not support attached fields.

The beauty of Views and custom content type is hiding all these programmatic switches in the nodes, never displaying them of course. It gets complicated, almost as much as writing your own code. Beware of the work levels this creates when you upgrade from D6 to D7.

Using very similar concepts, I am working on a site in Drupal 6 + Panels 3 + Views 2. The site uses Panels arguments, converted to Taxonomy Term context, and the context is passed to Views as view arguments.

So the page contains multiple views which fetch content based on the URL (typically, content tagged with said term, or Content Types containing a field which has a value that matches the Term or Term ID).

On the surface it all works - someone with permission to the taxonomy can simply create the appropriate terms, and magic empty placeholder pages become alive. Since the side navigation menus are built the same way (Views of existing published content based on weighted terms), the system will manage the menus automatically (although it is more work to set up vs. just using the Drupal Menu system with some theme overrides). Lastly, the "term" usage in the URL looks much nicer than using Node ID...

Before anyone goes down this path, be aware that you will very likely have ISSUES with page titles. Page Titles can be hardcoded in Panels. Or Panels can get Title from a View. This solution is good enough in simple cases but not a "hyper-dynamic" site.

The problem is, View Panes (in Panels) do not "know" about fields inside of the View including Node Title. You might think that inside the View Pane, one could check off "Set page title based on this Pane" but that's going to look INSIDE the pane for a manually set Page Title. Or you can tell Panels to use the View Title. But you can not tell a View to set View Title equal to your content's Node Title. Nor can Panels see any of the View fields.

For example, if your Panels URL is /support/faq/%term then you can fetch the right content OK, but that content can not tell Panels what the Page Title is... and Panels does not know what to ask. There's insufficient context.

Now, if your URL contains a number which represents Node ID: /support/faq/%nid then Panels has context. It can then do a context relationship (invoke the special 'Context' method of Views, providing you add a Context display type to your View).

Views Context does not (currently) support arguments, so suppose you had modified your FAQ View to return Node.Title based on a matching %term argument. You'll find the standalone View works perfectly... term gets you Title. But that will not work inside Panels, because although Panels can actually invoke the view's Context Display note that Panels will not actually SEND the arguments to the view. So your View Context will return (to Panels) whatever results it would produce if the standalone View had NO arguments at all (which is not what you want, if you're looking to get Page Titles).

For me, this problem is unsolved. There are "leads" which might produce results. The first lead is to export your Views, and then hack the code so that Views.Title gets set to whatever the Node.Title value was (and then tell Panels to set Page Title to whatever this pane's View Title was). I have not seen any examples of this online.

Second possibility is to export Panels, and hack that code. Using $vars and case statements (as is done here) you could craft a custom SQL query and set the page title. Again, no examples online.

Third approach is to hack the Template directly, but this would require a much larger list of URLs to switch off of, and some hand written rules. Worst of all this would be decoupled from either Panels or Views, so there wouldn't be any UI to manage things (not good).

Sorry for the long post - I do not have a blog as yet. :-). Hope this helps someone (or I see a comment containing a clue). Cheers. -Scott