3

Is it possible to conditionally include nodes in a view based on the paths specified in a field on that node? The idea is to essentially mimic the default property of blocks, making their display allowed or disallowed at specified paths. My view (technically a view block) is being used to show sponsor images as a slideshow, and I'd like to be able to define which pages each specific sponsors' graphics should display.

I'd imagine it would include the use of a contextual filter on the field containing the paths, but I can't figure out how it would work. Possibly via some implementation of Views Argument Substitutions, although that seems to base its results off of specified path arguments and not the whole path. In the meantime, I'm implementing Nodeblock as a partial substitute, but I'd prefer to leverage views if possible.

EDIT: Thanks to mchar's answer below, I was able to get a working snippet for this functionality. It could probably be optimized, but that's for another thread.

function MYMODULE_views_pre_render(&$view) {
    if($view->name=='sponsors') {
        $current_path = drupal_lookup_path('alias',current_path());
        foreach($view->result as $row_num => $row) {
            foreach($row->field_field_urls_to_show_up_on as $urlNum => $url) {
                $this_path = $url['rendered']['#markup'];

                // If the path contains an asterisk
                // Asterisks should only appear at the end of a path at the time of writing
                if (strpos($haystack = $this_path, $needle = '*') !== false) {
                    $this_path = str_replace('/*', '', $this_path);
                    if (strpos($haystack = $current_path, $needle = $this_path) === false) {
                        unset($view->result[$row_num]);
                    }
                }

                // if current_path is not the same as the provided path (no *)
                elseif ($current_path != $this_path) {
                    unset($view->result[$row_num]);
                }
            }
        }
    }
}
5
  • The idea is to essentially mimic the default property of blocks, making their display allowed or disallowed at specified paths. If you create a view block it will be listed in blocks management and you can specify paths for them too, just like regular blocks.
    – No Sssweat
    Commented Jan 16, 2016 at 22:34
  • I'd like the block itself to be displayed site wide. I'd like to filter the results by path.
    – Mrweiner
    Commented Jan 17, 2016 at 0:42
  • the specified paths are the nodes you want to show?
    – No Sssweat
    Commented Jan 24, 2016 at 6:09
  • The specified paths are not what I want to dispaly, but where I'd like my content to display. If I have this magical field on my node type, and one node has a value of /chickens (ideally potentially /chickens/*) and another node has a value of /dogs/terriers/brown, I'd like node 1 to only be included in my view block at /chickens (or /chickens/*) and I'd like node 2 to only be included in my view at /dogs/terriers/brown.
    – Mrweiner
    Commented Jan 24, 2016 at 16:51
  • You could create different content types. Chicken content type and Dogs content type. Then in view, Add Filter of Content Type and select chicken or dogs. Then create separate views for each. If you want a single view, another approach would be to use taxonomy terms and I think a contextual filter of taxonomy id would work here.
    – No Sssweat
    Commented Jan 25, 2016 at 7:05

3 Answers 3

1
+50

Hook views_pre_render should meet your needs.

Here is a sample code of what you are describing:

$string_pos = strpos($haystack = current_path(), $needle = 'chickens'); // or you may use drupal_get_path_alias()
  if ($view->name == 'view_name' && $view->current_display == 'view_display') {
    foreach($view->result as $row_num => $row) {
      if ($string_pos && strpos($haystack = $row->node_path, $needle = 'chickens')) {
        unset($view->result[$row_num]);
      }
    }
  }

It can be optimized but I guess you got the idea.

Hope that helps!

5
  • This definitely seems closer to what I'm looking for. The string I want to check is of course dyanmic depending on the node. So to modify this code, I would just set the value of $needle to the value of my field as served by the view, right?
    – Mrweiner
    Commented Jan 25, 2016 at 21:46
  • Although I haven't tested this yet, I'm awarding this answer. It looks the way that I would expect code to look if executing what I want to do. If I find it to not be the case, I'll amend what I can on here to make that clear.
    – Mrweiner
    Commented Jan 26, 2016 at 5:13
  • Sure, the $needle could be static or dynamic (the value of your field),check this out strpos.Should you have any question, post it.
    – mchar
    Commented Jan 26, 2016 at 9:55
  • Thanks! This code was the perfect starting point for me. I'm adding my final code as an edit to my question if you're interested in seeing my implementation.
    – Mrweiner
    Commented Jan 27, 2016 at 1:25
  • Perfect! and thanks for sharing your code, it is a good reference!
    – mchar
    Commented Jan 27, 2016 at 9:24
0
  1. Add an Entity reference field in the sponsor image content type.
  2. On every sponsor image node, refer the master content to which you need this sponsor to be displayed with.
  3. In your view, add a contextual filter on the above entity reference field, and Provide the default value -> Content ID from url.

This will filter the sponsor images those only refer the current node in the entity reference field.

5
  • This would work for node pages, but my block in this case is also displayed on non-entity pages (views pages, panels pages) which do not have entity IDs. In these cases, an entity reference field would be insufficient.
    – Mrweiner
    Commented Jan 19, 2016 at 17:35
  • How can we identify those non-entity pages where you are going to display your block? Any patterns? If it is views pages, what are the arguments you supply for those pages? If its panel pages, any contexts?
    – Kevin Siji
    Commented Jan 20, 2016 at 4:11
  • It's a fairly complex site. I believe they'd generally be a combination of views and panels, using panels everywhere. Hard to say exactly what the arguments/contexts would be. There's some variations based on where in the site you are.
    – Mrweiner
    Commented Jan 20, 2016 at 4:44
  • @Mrweiner "Is it possible to conditionally include nodes in a view based on the paths specified in a field on that node ?" so how do you plan on specifying paths for non-nodes?
    – No Sssweat
    Commented Jan 24, 2016 at 6:17
  • All the of the pages on the site of course have designated paths. This includes the non-node pages. Ideally I'd like to have a multivalue text/link field on my sponsor nodes (the ones in my view block) designating the paths on which to display.
    – Mrweiner
    Commented Jan 24, 2016 at 16:46
0

A> For non-node pages, set up a taxonomy with terms like the below and add it as a field to your sponsored posts content type.

User Pages
Search Pages
Login Page
Homepage
About Page
etc.

Then create multiple view blocks with each one only displaying on those pages using block settings. In each view, filter by that taxonomy term.

B> For node pages without panels, use Kevin Siji's answer.

C> For node pages that use panels, use Kevin Siji's answer but create a content pane. In Pane Settings, click Argument Input and select "From Context>Content ID" or maybe "From Panel Argument" but I think it's the first one.

That way, your sponsor can choose either nodes, page types, or both.

Bonus> For choosing nodes when creating a sponsored post, you can go one step further and have your entity reference field use an "entity reference view" to decide which nodes can be selected.

This allows you to add things like tiers where the user can choose "premium posts" for example. It also allows you to decide if sponsored posts should show on a regular node when you're creating it. Taxonomy or Booleans can achieve this because your "entity reference view" can filter them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.