When a crumb plugin like the path one evaluates a View it does not include the overwritten/updated Breadcrumb or create one of it's own it simply considers itself as on the root page of said view. It would be nice if it:

  • used any views breadcrumb overrides -or-
  • used the title if different from a parent path -or-
  • (if I win the willy wonka chocolate factory winning ticket for a feature request) had a token replacement form in the UI telling crumbs how to handle each contextual filter argument for specific a view.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

donquixote’s picture

I usually write custom site-specific plugins in those cases.

Are you talking about views pages with arguments, or with fixed url?
Duh, I should read the issue title :)

donquixote’s picture

Does the path of the views page contain an explicit % placeholder?

jpstrikesback’s picture

Yep, it does contain specific placeholders (I.e. blogs/%/%/%) and then various page displays walk upwards/backwards to/from there (blogs/user/year/month)

jpstrikesback’s picture

And yeah,I figured this was a site specific plugin use case...tho if there was a generalized way, that would be amaizyballs

donquixote’s picture

Ok, can you describe / spec out your use case in more detail, so I could reproduce it at home (or in my head), maybe I can do sth about it.
I like amaizyballs.

jpstrikesback’s picture

Awesome, will do later tonight!

jpstrikesback’s picture

OK so I have multiple views that use URL arguments to feed contextual filters (And some that use Term ID on Node/Term Page, etc). On these views when a Contextual Filter value is present or a default is provided I send that item to the Override Title & Override Breadcrumb. If we take a view of User Blogs which is available at:

/blogs

but also has a page display that is available at:

/blogs/USER

and:

/blogs/USER/YEAR

and:

/blogs/USER/YEAR/MONTH

for each Contextual filter I override the breadcrumb with a input value from the URL (or wherever I get the contextual filter input from). This works for normal breadcrumbs but only shows the root view (i.e. Blogs from /blogs) as a valid parent when Crumbs evaluates the path. It's probably by design, but the breadcrumbs work when crumb is disabled, and disappear when enabled. I currently use Context to place the crumbs breadcrumbs where I want them (and disable normal breadcrumbs in Omega)

Let me know if that was useful as a usecase or if you want more info.

donquixote’s picture

Ok. So it is all the same display you use for /blogs/USER, /blogs/USER/YEAR etc? Or are these separate displays?
Maybe it helps to have separate displays for each ..

Also it would be interesting what you find in the menu_router table for those views paths. Do you find blogs/% and blogs/%/% and blogs/%/%/%, or only just blogs/% ?

jpstrikesback’s picture

Each one is a separate display:

/blogs (landing, no argument)
/blogs/user (/blogs/%)
/blogs/user/year (/blogs/%/%)
/blogs/user/year/month (/blogs/%/%/%)

Just checked the menu_router table and each of the display paths are in there (blogs, blogs/%, blogs/%/%, blogs/%/%/%)

Now, just to give some more background on this specific set of views/displays there is more to it which may or may not be pertinent but I'll include it for good measure:

There is an additional view with displays that loads some of the above displays via a No Results Global View Area for some of the displays, maybe this has an impact so I'll list the full monty of displays and inheritance:

blogs
blogs/YEAR ->no results go to blogs/USER
blogs/YEAR/MONTH ->no results go to blogs/USER/YEAR
blogs/USER/YEAR/MONTH

That is a total of 6 displays staggered. Some of them share the same path and the winner is determined by the order of the views & displays...but it works.

donquixote’s picture

And with Crumbs, the breadcrumb you get on blogs/USER/YEAR/MONTH is just blogs/ ?
Can you check in menu_router table what is the title and title callback for those items?

jpstrikesback’s picture

Yup, just "blogs" with crumbs (NOTE: as if it is on the /blogs page, as I have it set to show the current page after the breadcrumb)

Actually the title is only set for the root path to the views (it is set to Blogs), the callback is simply t() for that and all the others. I set the title dynamically via the contextual filter so I have never set the default title for these displays.

donquixote’s picture

Ah, very interesting!
I had a look myself, and indeed Views does not set a title or title callback for those paths.
That's a pity, because if the title is empty, the breadcrumb item will be skipped.

Solution:
We should write a Crumbs plugin with findTitle(), that should determine the correct title for those breadcrumb items.
Could you draft something? I assume you already made a custom plugin, so you are maybe half the way already :)

donquixote’s picture

Or we could ask over at views if they can do something for us :)
Would be nice if Views would put something more useful into the menu_router table.

jpstrikesback’s picture

I haven't started one yet, but I will either tmrw or friday, in a perfect world what would views do?

donquixote’s picture

Views should register a title callback that is based on the title setting.
Or, to not mess around with existing sites, it could provide an additional setting to determine the title callback.

Btw, I tried creating a view with an "author uid" argument, and configured %1 for the dynamic title, but this only sets the uid as the title, instead of the node author name. any idea how to get the node author name instead?

jpstrikesback’s picture

Mm, interesting, would one then pick their favourite source for the title callback or something (in the case of an additional setting)? As far as the author UID I've made a bunch of contextual filters and validators I should probably throw in a sandbox that let me grab a UID from a aliased username out of a path component, then for the title I use first result row substitutions (you can do that, it's just not documented) via the content author relationship. Then when I am spitting the input back into the breadcrumb it uses what it was given via the filter.

jpstrikesback’s picture

Oh, I believe you can also substitute !1 for %1 to get the item title/name

donquixote’s picture

#16
wow, this sounds complex :)

I usually don't use views pages with arguments at all. Instead I use entityaspect + display suite dynamic fields + views content pane. This also allows to put display other fields of the entity (e.g. the user) next to the view.
However, this only works for entity paths so far. Would be interesting to make a more generic "routeaspect", and display suite to have additional fields based on additional wildcard arguments :).

donquixote’s picture

On Views queue:
#616922-5: Set title in menu_router table
(This is an old issue, so it could happen that someone decides that a new issue should be opened instead)

jpstrikesback’s picture

Wow, entityaspect looks very, very cool!

donquixote’s picture

Ok, if you want to do something on Crumbs, the first step would be to grep in Views for drupal_set_breadcrumb(), and see how they load the information necessary to build the breadcrumb.
(I suppose they have to load the entire view, which is a bit unfortunate)

pnigro’s picture

I am experiencing the same problem when a taxonomy term page is overridden by a view at path taxonomy/term/%. The title of the taxonomy term page is empty when _findTitle tries to find it. In the current version of Views, 7.x-3.5, the breadcrumb is set within the function get_breadcrumb in view.inc line 1656. It looks as though the view would have to be loaded. I would love to see this feature added. I am still learning how to code. but I can test.

Thanks
Paul

  /**
   * Get the breadcrumb used for this view.
   *
   * @param $set
   *   If true, use drupal_set_breadcrumb() to install the breadcrumb.
   */
  function get_breadcrumb($set = FALSE) {
    // Now that we've built the view, extract the breadcrumb.
    $base = TRUE;
    $breadcrumb = array();

    if (!empty($this->build_info['breadcrumb'])) {
      foreach ($this->build_info['breadcrumb'] as $path => $title) {
        // Check to see if the frontpage is in the breadcrumb trail; if it
        // is, we'll remove that from the actual breadcrumb later.
        if ($path == variable_get('site_frontpage', 'node')) {
          $base = FALSE;
          $title = t('Home');
        }
        if ($title) {
          $breadcrumb[] = l($title, $path, array('html' => TRUE));
        }
      }

      if ($set) {
        if ($base) {
          $breadcrumb = array_merge(drupal_get_breadcrumb(), $breadcrumb);
        }
        drupal_set_breadcrumb($breadcrumb);
      }
    }
    return $breadcrumb;
  }
jpstrikesback’s picture

Ok this may be a big silly question (cause I still haven't dug in, will shortly) couldn't we hijack/piggy back on drupal_get_breadcrumb since views has just loaded it up for us?

donquixote’s picture

#23,
#1794764: Provide a "legacy" plugin

I have some objections to drupal_set_breadcrumb(), because this breadcrumb is not available on child pages.

I am experimenting with a custom Crumbs plugin myself now..

jpstrikesback’s picture

I think you may need a new handle, something like quickdrawquixote ^^ :) re #1794764: Provide a "legacy" plugin fair points especially hook_init, I just cringe at the thought of loading the view again to get the crumb, tho if everything is cached up the ___ then maybe it's ok?

donquixote’s picture

FileSize
1.26 KB

I don't really know how the view is cached, I just suppose it is.
I did a quick experiment where it said that it needs around 5-6 millis.

My local codebase is currently a bit messed up, so I don't post a patch. Instead
- Download the crumbs.views.inc.txt, rename it to crumbs.views.inc, and put it into the plugins/ folder of crumbs.
- Modify crumbs_get_plugins() in crumbs.module to add "views" in the list of modules supported by default.
- Clear the cache.

The file contains some benchmark code, I thought you might be interested in that.

donquixote’s picture

Here is the essential stuff I do with the view:

      $view = views_get_view($name);
      $view->set_display($display_id);
      $view->pre_execute($args);
      $view->build($display_id);
      if (!empty($view->build_info['breadcrumb'])) {
        return array_pop($view->build_info['breadcrumb']);
      }

There might be an easier way to do all this..
The important thing is that we don't execute() or render() the view.

donquixote’s picture

Hmm,
maybe a bad idea to array_pop() and thus modify the view itself.
Might be better to copy the breadcrumb before we pop(), or just say end().

jpstrikesback’s picture

This pretty much works. For my use case (all the views embedding) it needs a few extra (painful) additions:

      foreach (array($view->field, $view->header, $view->footer, $view->empty) as $area) {
        foreach ($area as $empty => $handler) {
          if (strpos($empty, 'view') === 0) {
            $view->display_handler->execute();
            $view->post_execute();
          }
        }
      }

Normal area views (that ship with views) actually don't send a breadcrumb back so I'm using this: Views Area View with More, the whole thing is a bit bad already (executes a cloned view), but now I've found that a view areas rendered title & crumbs don't necessarily get cached with the view it would seem so I'm thinking around that a bit...like maybe imitating all the work views does to prepare it's crumbs...thanks for all of this!!!

donquixote’s picture

Have you considered using panels?
I don't have much experience with that, but afaik it lets you define the page and arguments independent of the views you put on the page.

donquixote’s picture

Cool stuff:
There are reasons why we don't use drupal_get_breadcrumb() in findParent().
But we can use it in findTitle() !
At the moment that this plugin method fires, the drupal_get_breadcrumb() is already filled. So we could base the views plugin on drupal_get_breadcrumb().

------

Just tried this, and found this:
drupal_get_breadcrumb():

(Array, 3 elements)
0 (String, 22 characters) <a href="/en">Home</a>
1 (String, 36 characters) <a href="/en/news/all/all">admin</a>
2 (String, 33 characters) <a href="/en/news/1/all">2012</a>

The links and titles are messed up!!
If you click on the piece saying "admin", you would be sent to the main unfiltered view. If you click on "2012" you would be sent to the view filtered by uid, but not to the one filtered by year.
Ouch.

jpstrikesback’s picture

Ha! I was playing around with that and found out the same, but one could do a strip tags and then merge with the item map perhaps?

donquixote’s picture

FileSize
1.62 KB

I want a safe way to know which title maps to which path. I wanted to use the href for that.
Attached is yet another attempt of a crumbs.views.inc plugin.

donquixote’s picture

Views queue: #1919456-2: Views breadcrumb: Wrong href for titles
In combination with this patch on views, I get the correct breadcrumbs for my views.

donquixote’s picture

#34: Turns out this is actually not a bug in views but the intended behavior.

---------------------

Completely new approach!
One patch for 7.x-1.x, another for 7.x-2.x

How to use:
- Create a view with the typical News > (year) > (month) > (day)
- (multiple displays with news, news/%, news/%/%, news/%/%/%)
- (no breadcrumb configuration within views needed)
- Set news/[node:created:custom:Y/m/d] as entity parent for news.
- Apply the patch.
- Visit one of the news.
-> Profit.

donquixote’s picture

Status: Active » Needs review

I still have some performance concerns.
But please, test it!

Status: Needs review » Needs work

The last submitted patch, crumbs-7.x-2.x-views-contextual-filters-1914718-35.patch, failed testing.

donquixote’s picture

Removing brackets around the titles (only had them to prove that the plugin is in effect).

Btw, branch stays on 7.x-1.x, because we start with the older branch and merge upwards.

Status: Needs review » Needs work

The last submitted patch, crumbs-7.x-2.x-views-contextual-filters-1914718-37.patch, failed testing.

donquixote’s picture

Status: Needs work » Needs review
donquixote’s picture

donquixote’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev

Queuing up the 7.x-2.x patches

donquixote’s picture

donquixote’s picture

jpstrikesback’s picture

Version: 7.x-1.x-dev » 7.x-1.1
FileSize
4.72 KB

Flipping fantastic!! Way better performance than I had running (I was building my views and then executing embedded views)!

Here is a version that takes care of embedded views and null arguments.

Check out the TODO and tell me if you can see anything wrong here, I've tested this on the rather complex setup detailed in #9 above and all works well.

Cheers!

Version: 7.x-2.x-dev » 7.x-1.1
Status: Needs review » Needs work

The last submitted patch, crumbs-7.x-1.x-views-contextual-filters-1914718-45.patch, failed testing.

jpstrikesback’s picture

Version: 7.x-1.1 » 7.x-1.x-dev
Status: Needs work » Needs review

wrong version

jpstrikesback’s picture

donquixote’s picture

Version: 7.x-1.1 » 7.x-1.x-dev

Here is a version that takes care of embedded views

Am I correct in assuming that this is rather an edge case, which only applies with your sandbox?
If not, please enlighten me :)

I would suggest to keep the main views plugin simple (only support page views).
Then there can be an additional plugin for embedded views. Might even be part of your sandbox instead of Crumbs.

And keep in mind, there is still the option of site-specific Crumbs plugins.

The implementation I suggested does not even care about the breadcrumb config of the view. It always gets the title from the last argument, no matter how that is configured. If you are not happy with that, you need to disable the plugin for this specific views display, and/or override it with your own.

null arguments

Have not really thought about this. +1.

donquixote’s picture

The implementation I suggested does not even care about the breadcrumb config of the view. It always gets the title from the last argument, no matter how that is configured. If you are not happy with that, you need to disable the plugin for this specific views display, and/or override it with your own.

This has a benefit:
With the usual Views breadcrumb, you never get the last item.
If you have the typical news/%/%/% with
News > (year) > (month) > (day), what you would do in views config is this:
first argument (year): breadcrumb name: NOTHING
second argument (month): breadcrumb name: %1 (year)
third argument (day): breadcrumb name: %2 (month)

So if you visit a day display, you get a breadcrumb of
News > (year) > (month) >
so the day is not part of the breadcrumb (only of the page title)

If you visit a news node, and want the breadcrumb to be provided by the view, respecting the views config, then you can never have the day as part of the breadcrumb.
Same if you want to always show the current page in the breadcrumb.

Besides, the behavior I suggested seems like a very solid default.
I consider it more likely that people mess up (or simply don't care about) the views breadcrumb config, than people wanting a non-default behavior.

donquixote’s picture

#9

blogs
blogs/YEAR ->no results go to blogs/USER
blogs/YEAR/MONTH ->no results go to blogs/USER/YEAR
blogs/USER/YEAR/MONTH

just wondering.. is this a good design?
What I can imagine as reasonable behavior is this:

Blogs > 2013 > June
There are no results for June 2013. Instead here is some of your personal blog.

The idea being that the user intended to see the blog posts from June 2013.
If we show something else instead, we need to give an explanation.
And for the breadcrumb: Imo better to let it indicate that "yes, this is the place you were looking for. We are out of order atm, but you can stop searching". So, even if you show something else in the "no results", that should not affect the breadcrumb. Because if it does, it can feel to the user like she has mis-clicked.

If you still want the breadcrumb to be modified based on the embedded view, I am sure this can be done with a custom site-specific plugin.

jpstrikesback’s picture

Heh heh, lots to reply to :) here goes:

Am I correct in assuming that this is rather an edge case, which only applies with your sandbox?
If not, please enlighten me :)

It is an edge case, as are embedded views that pass anything back. That said, if embedded items are checked then my sandbox isn't actually required for setting the breadcrumb. I.E. crumbs provides that (with the patch I added above). Tho I'm all for this being site specific / custom plugin.

The implementation I suggested does not even care about the breadcrumb config of the view. It always gets the title from the last argument, no matter how that is configured. If you are not happy with that, you need to disable the plugin for this specific views display, and/or override it with your own.

I love this, it's perfect IMO other than not handling null arguments.

blogs
blogs/YEAR ->no results go to blogs/USER
blogs/YEAR/MONTH ->no results go to blogs/USER/YEAR
blogs/USER/YEAR/MONTH

just wondering.. is this a good design?

The idea is that I needed to be able to validate an argument at (eg.) position 2 that is either a DATE or a USER and allow the first one that passed validation to render/modify the query. Definitely an edge case, and pushing views in places it doesn't exactly want to be perhaps. Changing the design to USER/blog could possibly work for the usecase (not sure off hand).

donquixote’s picture

edge edge edge.

Ok can you help with the "null arguments" ?

jpstrikesback’s picture

Sure, on a scale from ugly to works where we at with how I did it up there?

Roughly:


      // Check the last argument for a breadcrumb item title.
      $last_arg = end($view->argument);
      if (!is_object($last_arg)) {
        return;
      }
      elseif ($last_arg->is_exception()) {
        return;
        // $last_arg_title = $last_arg->exception_title();
      }
      else {
        $last_arg_title = $last_arg->get_title();
      }

      // Ignore NULL arguments if they don't produce a title
      // and evalutate the argument preceding if it exists.
      // Null arguments are special as they allow one to ignore an argument
      // but still set a title & breadcrumb
      if ($last_arg instanceof views_handler_argument_null && empty($last_arg_title)) {
        $last_arg = prev($view->argument);

        if ($last_arg && !is_object($last_arg)) {
          return;
        }
        elseif ($last_arg->is_exception()) {
          return;
          // $last_arg_title = $last_arg->exception_title();
        }
        else {
          $last_arg_title = $last_arg->get_title();
        }
      }
donquixote’s picture

I don't really know, the #45 had a lot of stuff for the embedded views which I was not so motivated to study.
(esp. because I am traveling and rather wanted to see Pompei :) )

I was hoping for a stripped-down version, consisting of #38 with added null handling, and an interdiff to #38 (don't care which branch)

But, let me have a look at the snippet in #54.

  $last_arg = prev($view->argument);

I wonder if we need that. Can you explain a bit about the use case?

E.g. in the example I gave we have these views displays:
news/%/%/% -> news for a given day
news/%/% -> news for a given month
news/% -> news for a given year
news -> all news
In the breadcrumb we work our way through all the displays, and only ever look at the last argument.

But, what if we only had the day thing and the "all news"?
news/%/%/%
news
Which breadcrumb would be intended?

jpstrikesback’s picture

My thinking on grabbing the previous argument handlers title is that if a null handler is being using and it doesn't provide a title it is being used to ignore some contextual value, and since we only care at this point in evaluation for the last argument we should at this point move back one and ignore the null argument...

But, what if we only had the day thing and the "all news"?
news/%/%/%
news
Which breadcrumb would be intended?

IMO this is a view design problem :) At least if the designer wants sane breadcrumbs with crumbs :) ...Do we somehow construct a fallback that extracts the full breadcrumb as given from $view->build_info['breadcrumb']?

donquixote’s picture

Can you give an example situation for a null argument?
As in: Views config, argument values, and intended breadcrumb.

bojanz’s picture

Patch in #38 solves my use case perfectly.

Attaching version that applies against 1.9, so that I can add it to Kickstart (we could use a new 7.x-1.x release, btw).

donquixote’s picture

I wonder if we can further speed it up with caching.
I think it would be justified to do this as a one-off only for this plugin, because views tend to be more expensive to load than terms, nodes or users. (the debug page will tell you)

donquixote’s picture

It is a shame that views argument handlers can only be used in combination with the view, and not standalone.

donquixote’s picture

Status: Needs review » Fixed

Pushed to 7.x-2.x.

lmeurs’s picture

@donquixote: When you say "Pushed to 7.x-2.x.", do you mean the fix is available in the latest dev release?

The problem still occurs with 7.x-2.0-beta1+0-dev, downgrading to 7.x-1.10+0-dev solved the issue for me.

I used simplytest.me with just Views and Crumbs installed. I enabled the taxonomy/term/% view, cleared the cache, created an article with a tag, visited the tag's term page and got the following error:

Fatal error: Class name must be a valid object or a string in /home/sf5cad58330ac4db/www/includes/common.inc on line 7809

Thanks for the great work!

donquixote’s picture

7.x-2.0-beta1+0-dev

What is "+0-dev" ?

Going to try myself now.

jpstrikesback’s picture

Just FYI I just upgraded to 7.x-2.x-dev and without a little cache clear I received a rather awesome:

"method_exists(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "crumbs_CrumbsMultiPlugin_NodeParent" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition" in sites/all/modules/crumbs/lib/PluginInfo.php:170

After a cache clear all was well again.

donquixote’s picture

@jpstrikesback: Ok, I think I know why.
I recently killed the class crumbs_CrumbsMultiPlugin_NodeParent. But git checkout does not trigger a cache clear.
On the other hand, regular module update does trigger a cache clear. So I guess this is something we can live with.

donquixote’s picture

@lmeurs: Could I have a stack trace?
Can you enable devel on simplytest.me and tell it to show a stack trace?

jpstrikesback’s picture

Ah interesting, I did it via drush, but yeah, can totally live with it...

Also, all of my taxonomyesque view pages are working (tho I've turned off the normal displays with Taxonomy Display module and use views magik™)

donquixote’s picture

I did it via drush

Hm.. maybe it only flushes if there is actually a hook_update_N() going on?
Maybe I will add an emtpy hook_update_N() in the next beta.

lmeurs’s picture

@donquixote: Sorry for the late reply, I was gone on vacation. :-)

The "+0-dev" version number suffix was added by the drupal.org packaging script to the version number inside the .info file.

With the beta7 version I cannot reproduce the error anymore, great! Later on I will try this latest release on the development project.

Thanks again!

lmeurs’s picture

@donquixote: Installed and quickly tested 7.x-2.0-beta9, so far so good!

donquixote’s picture

There seems to be a problem with htmlentities in the title provided by the views plugin.
#2074549: Taxonomy titles with & displaying as html entity &amp;

Views already runs htmlentities, then Crumbs does it again.
Can someone have a look at the other issue and confirm the problem and solution?
Having a 3rd pair of eyes is always useful!

Thanks!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

donquixote’s picture

Hey everyone..
As this has been one of the more frequented issues, I would like to take the chance for a bit of "advertising", for everyone who is going to attend DrupalCon.
#2094933: Crumbs BoF/meeting on DrupalCon Prague 2013?

The format and time is not decided yet, and will depend on the feedback I get. For my own taste, it could be some time during the code sprints, or in the evenings - so none of us will miss any sessions.

(and no worries, I am not going to spam every issue with this, only a few)

donquixote’s picture

Issue summary: View changes

Updated issue summary.